package parse

// yaml解析规则：
// 1、第一种类型是标量（scalar），也就是一个单独的字符串（string）或数字（numbers），比如"北京"这个单独的词。
// 2、第二种类型是序列（sequence），也就是若干个相关的数据按照一定顺序并列在一起，又叫做数组（array）或列表（List），比如"北京，上海"。
// 3、第三种类型是映射（mapping），也就是一个名/值对（Name/value），即数据有一个名称，还有一个与之相对应的值，这又称作散列（hash）或字典（dictionary），比如"首都：北京"。
// 4、如果同一目录下面出现重复的映射，取后面定义的值为准，对于使用include的情况，需要注意值覆盖问题，特殊值放在include后面定义
import (
	"io/ioutil"
	"log"
	"myutil"

	"gopkg.in/yaml.v2"
)

// EventsBlock parameters
type EventsBlock struct {
	// Worker_connections max connections
	WorkerConnections int
	// Multi_accept set flag on is true,off is false
	MultiAccept string
}

// HTTPBlock block info,maybe has Https,TCP and so on
type HTTPBlock struct {
	DefaultType              string   // MIME type
	AccessLog                string   // access log file
	KeepaliveTimeout         int      // default time unit millisecond
	Gzip                     string   // on is true, off is false
	GzipDisable              string   // regular expression no use
	ClientHeaderBufferSize   string   // numbers with unit likes : 1K,2M,4G ...
	LargeClientHeaderBuffers []string `yaml:",flow"` // multi_params parse in slice
	ServerBlocks                      // expand ServerBlock slice
}

// ServerBlock server block
type ServerBlock struct {
	Listen         int      // listen port number
	ServerName     []string // hostname slice,surport domain or IPV4/IPV6
	AccessLog      string   // serverBlock accesslog filename.if set,replace parent set,like HTTPBlock
	LogFormat      string   // log format,directive or variable surport
	LocationBlocks          // expand LocationBlock slice
}

// LocationBlock handler location block
type LocationBlock struct {
	MatchPath string   // uri string,next with surport regular expression
	Handler   string   // handler function name,need with pkg name,like handle.DefaultReturnHandler1
	Root      string   // set root path
	Index     []string `yaml:",flow"` // default find file name with match postfix,like *.html
	Expires   string   // set expire time
	Includes  string
}

// ServerBlocks multi ServerBlock
type ServerBlocks []ServerBlock

// LocationBlocks multi LocationBlock in one ServerBlock
type LocationBlocks []LocationBlock

// ServerConf assembly in one struct,this include all config
type ServerConf struct {
	SysUser         string `yaml:"user"` // rename user to SysUser,not use root account
	WorkerProcesses int    // set use CPU numbers
	ErrorLog        string // http or https level errorlog,maybi replaced by server or location
	Pid             string // pid sock file
	EventsBlock            // expand EventsBlock here
	HTTPBlock              // expand HTTPBlock
}

// ParseFile method , input is *file
func (serverConf *ServerConf) ParseFile(confFile *string) error {
	buf, err := ioutil.ReadFile(*confFile)
	if err != nil {
		return err
	}
	err1 := yaml.Unmarshal(buf, serverConf)
	if err1 != nil {
		log.Fatalf("error: %v", err1)
		return err1
	}

	return nil
}

// ParseBuf method input is []byte
func (serverConf *ServerConf) ParseBuf(buf []byte) error {
	err := yaml.Unmarshal(buf, serverConf)
	if err != nil {
		log.Fatalf("error Unmarshal : %v", err)
		return err
	}

	return nil
}

// Parser read the first file
func (serverConf *ServerConf) Parser(fileName, delim string) error {
	output := myutil.Parser(fileName, delim)

	return serverConf.ParseBuf(output)
}
